#include <windows.h>    // include the basic windows header file
#include <windowsx.h>
#include "DirectX.h"
#include "Input_Win32.h"
#include "../Flying-Racoon-Potato/Simulation.h"

namespace ApplicationDefaultParameters
{
	static const UINT uiDefaultWidth = 800;
	static const UINT uiDefaultHeight = 600;
}

namespace ApplicationServices
{
	DirectX renderer;
	Input_Win32 input;
}


// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
	UINT message,
	WPARAM wParam,
	LPARAM lParam);


int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{

// 	DirectX renderer;
// 	Input_Win32 input;
	// this struct holds information for the window class
	WNDCLASSEX wc;

	// clear out the window class for use
	ZeroMemory(&wc, sizeof(WNDCLASSEX));

	// fill in the struct with the needed information
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wc.lpszClassName = TEXT("WindowClass1");

	// register the window class
	RegisterClassEx(&wc);

	// create the window and use the result as the handle
	HWND hWND = CreateWindowEx(NULL,
		TEXT("WindowClass1"),    // name of the window class
		TEXT("BuildCreateDestroy"),   // title of the window
		WS_OVERLAPPEDWINDOW,    // window style
		100,    // x-position of the window
		100,    // y-position of the window
		ApplicationDefaultParameters::uiDefaultWidth,    // width of the window
		ApplicationDefaultParameters::uiDefaultHeight,    // height of the window
		NULL,    // we have no parent window, NULL
		NULL,    // we aren't using menus, NULL
		hInstance,    // application handle
		NULL);    // used with multiple windows, NULL

	if( !ApplicationServices::renderer.Init( hWND
					  , ApplicationDefaultParameters::uiDefaultWidth
					  , ApplicationDefaultParameters::uiDefaultHeight) )
	{
		OutputDebugString(TEXT("Failed to create D3D device"));
		return 0;
	}

	ApplicationServices::renderer.LoadShaders();
	//   if( MessageBox(hWnd,
	//              L"Run Application?",
	//              L"BuildCreateDestroy",
	//              MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL)
	//{
	//	return 0;
	//}


	// display the window on the screen
	ShowWindow(hWND, nCmdShow);

	//define these somewhere
	unsigned int currentframe(0);
	double framerate(0);
	double oldtime(0);
	double newtime(0);
	__int64 counter(0);
	__int64 frequency(0);
	double timeperframe(0);

	Simluation simulation;
	simulation.Init();

	// enter the main loop:

	// this struct holds Windows event messages
	MSG msg;

	bool bRunning = true;
	while(bRunning)
	{
		//framerate management, call this every frame
		QueryPerformanceCounter( (LARGE_INTEGER*)&counter );
		QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency );
		newtime = ((double)counter / (double)frequency) * 1000;
		timeperframe = newtime - oldtime;
		framerate = 1.0 / timeperframe;
		oldtime = newtime;
		currentframe++;

		// Check to see if any messages are waiting in the queue
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			// translate keystroke messages into the right format
			TranslateMessage(&msg);

			switch(msg.message)
			{
			case WM_QUIT: bRunning = false;
				break;
			}

			// send the message to the WindowProc function
			DispatchMessage(&msg);


		}



		// Run game code here
		// ...
		// ...
		ApplicationServices::renderer.render_frame(newtime);
	}

	// return this part of the WM_QUIT message to Windows
	return msg.wParam;

}




// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	// sort through and find what code to run for the message given
	switch(message)
	{
		//this message is read when the window is closed
	case WM_DESTROY:
		{
			// close the application entirely
			PostQuitMessage(0);
			return 0;
		} 
		break;

	}
	ApplicationServices::input.Update(message,wParam);

	// Handle any messages the switch statement didn't
	return DefWindowProc (hWnd, message, wParam, lParam);
}

